package com.rizzo.infrastructure.amqp.rabbit.log4j;

import org.cloudfoundry.runtime.env.CloudEnvironment;
import org.cloudfoundry.runtime.env.RabbitServiceInfo;
import org.cloudfoundry.runtime.env.RedisServiceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.util.Log4jWebConfigurer;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.List;

/**
 * Dynamic configuration of Log4j with an AMQP appender.
 */
public class Log4jConfigListener implements ServletContextListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(Log4jConfigListener.class);

    public void contextInitialized(ServletContextEvent event) {
        Log4jWebConfigurer.initLogging(event.getServletContext());

        CloudEnvironment cloudEnvironment = new CloudEnvironment();
        if (cloudEnvironment.isCloudFoundry()) {
            LOGGER.info("Configuring Log4j Config in the cloud");
            initCloudFoundryAppender(cloudEnvironment);
        } else {
            LOGGER.info("Configuring Log4j Config locally");
            initLocalAppender();
        }
    }

    public void contextDestroyed(ServletContextEvent event) {
        Log4jWebConfigurer.shutdownLogging(event.getServletContext());
    }

    void initCloudFoundryAppender(CloudEnvironment env) {
        try {
            List<RabbitServiceInfo> rabbitServiceInfos = env.getServiceInfos(RabbitServiceInfo.class);
            for (RabbitServiceInfo serviceInfo : rabbitServiceInfos) {
                LOGGER.info("Available rabbit-services: " + serviceInfo.getServiceName());
            }
            List<RedisServiceInfo> redisServiceInfos = env.getServiceInfos(RedisServiceInfo.class);
            for (RedisServiceInfo serviceInfo : redisServiceInfos) {
                LOGGER.info("Available redis-services: " + serviceInfo.getServiceName());
            }
            RabbitServiceInfo rabbitServiceInfo = env.getServiceInfo("rabbitmq-analytics", RabbitServiceInfo.class);
            AmqpJsonAppender amqpAppender = getAmqpAppender();
            amqpAppender.close(); // Required for changes to take effect
            amqpAppender.setHost(rabbitServiceInfo.getHost());
            amqpAppender.setPort(rabbitServiceInfo.getPort());
            amqpAppender.setVirtualHost(rabbitServiceInfo.getVirtualHost());
            amqpAppender.setUsername(rabbitServiceInfo.getUserName());
            amqpAppender.setPassword(rabbitServiceInfo.getPassword());
            amqpAppender.setInstanceName(env.getInstanceInfo().getName());
            amqpAppender.setInstanceIndex(env.getInstanceInfo().getInstanceIndex());
        } catch (Throwable t) {
            LOGGER.error("Failure while configuring AmqpAppender", t);
        }
    }

    void initLocalAppender() {
        try {
            AmqpJsonAppender amqpAppender = getAmqpAppender();
            amqpAppender.close(); // Required for changes to take effect
            amqpAppender.setHost("localhost");
            amqpAppender.setPort(6379);
            amqpAppender.setVirtualHost("/");
            amqpAppender.setUsername("guest");
            amqpAppender.setPassword("guest");
        } catch (Throwable t) {
            LOGGER.error("Failure while configuring AmqpAppender", t);
        }
    }

    AmqpJsonAppender getAmqpAppender() {
        return (AmqpJsonAppender) org.apache.log4j.Logger.getRootLogger().getAppender("amqp");
    }
}
